package simpleWave;

import java.util.ArrayList;
import java.util.LinkedList;

import data.PersonData;
import data.Stadium;

public class PersonProcess extends Thread {
	
	private PersonData personData;
	
	private PersonProcess personToLeft;
	private PersonProcess personToRight;
	private boolean isWaveStarter = false;
	private boolean isRandomlyStartingWaves = true;
	private int startingWaveChance = 2;
	
	private boolean verifiedWave;
	
	private Synchronizer synchronizer;
	
	private ArrayList<Stadium> history;

	public synchronized ArrayList<Stadium> getHistory() {
		return history;
	}

	public void setHistory(ArrayList<Stadium> history) {
		this.history = history;
	}

	public PersonProcess(Synchronizer synchronizer) {
		this.synchronizer = synchronizer;
	}

	public void run() {
		// run verifier?
		init();
		while (true) {
			if (isRandomlyStartingWaves) {
				considerStartingWave();
			}
			
			boolean neighbourStanding = lookAround();
			
			//this.synchronizer.checkIn(this.getId());
			
			if (neighbourStanding) {
				this.standUp();
				
				this.synchronizer.checkIn(this.getId());
				
				this.sitDown();
				
				this.synchronizer.checkIn(this.getId());
				
				this.synchronizer.checkIn(this.getId());

			} else {
				this.synchronizer.checkIn(this.getId());
			}
			
		}
	}

	private void init() {
		if (isWaveStarter) {
			startWave();
		}
	}
	
	private void considerStartingWave() {
		int chance = (int) Math.round(Math.random() * 99) + 1;
		if (startingWaveChance >= chance) {
			startWave();
		}
	}
	
	public boolean lookAround() {
		return (lookRight() || lookLeft());
		/*try {
			sleep(100);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	}

	private boolean lookRight() {
		// If no history exists, we have nothing to look at
		if (history.size() < 1) {
			return false;
		}
		
		// Retrieve latest stadium, if none return false
		Stadium stadium = history.get(history.size()-1);
		
		// Retrieve row
		ArrayList<PersonData> row = stadium.getRow();
		
		//If we are last in row, there can't be nobody to the right
		if (personData.getPersonId() >= (row.size()-1)) {
			return false;
		}
		
		// Retrieve person to right, if any
		PersonData personToRight = row.get(personData.getPersonId()+1);
		if (personToRight.getPersonState() == PersonData.PersonState.STANDING) {
			return true;
		} else {
			return false;
		}
	}
	
	private boolean lookLeft() {
		// If no history exists, we have nothing to look at
		if (history.size() < 1) {
			return false;
		}
		
		// Retrieve latest stadium, if none return false
		Stadium stadium = history.get(history.size()-1);
		
		// Retrieve row
		ArrayList<PersonData> row = stadium.getRow();
		
		// If we are first in row, there can be nobody to the left
		if (personData.getPersonId() <= 0) {
			return false;
		}
		
		// Retrieve person to left, if any
		PersonData personToLeft = row.get(personData.getPersonId()-1);
		if (personToLeft.getPersonState() == PersonData.PersonState.STANDING) {
			return true;
		} else {
			return false;
		}
	}
	
	public void startWave() {
		//this.personState = PersonState.STANDING;
		this.synchronizer.checkIn(this.getId());
		standUp();
		this.synchronizer.checkIn(this.getId());
		sitDown();
		this.synchronizer.checkIn(this.getId());
		this.synchronizer.checkIn(this.getId());
	}

	public void standUp() {
		/*try {
			sleep(1000);
		} catch (InterruptedException e) {
			System.out.println("Sleep failed");
			e.printStackTrace();
		}*/
		this.personData.setPersonState(PersonData.PersonState.STANDING);
	}
	
	public void sitDown() {
		/*try {
			sleep(1000);
		} catch (InterruptedException e) {
			System.out.println("Sleep failed");
			e.printStackTrace();
		}*/
		this.personData.setPersonState(PersonData.PersonState.SITTING);
		/*try {
			sleep(2000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}*/
	}
	
	public String toString() {
		return this.personData.toString();
	}

	public PersonData getPersonData() {
		return personData;
	}

	public void setPersonData(PersonData personData) {
		this.personData = personData;
	}

	public boolean isRandomlyStartingWaves() {
		return isRandomlyStartingWaves;
	}

	public void setRandomlyStartingWaves(boolean isRandomlyStartingWaves) {
		this.isRandomlyStartingWaves = isRandomlyStartingWaves;
	}

	public boolean isWaveStarter() {
		return isWaveStarter;
	}

	public void setWaveStarter(boolean waveStarter) {
		this.isWaveStarter = waveStarter;
	}

	public void setVerifiedWave(boolean verifiedWave) {
		this.verifiedWave = verifiedWave;
	}

	public boolean isVerifiedWave() {
		return verifiedWave;
	}
}
